Amazon DocumentDBの変更ストリームをイベントソースとしてAWS Lambdaを実行させてみた
こんにちは。サービス部の武田です。
AWS Lambdaはイベントソースマッピングを使用することで、イベントソースの変更をトリガーにLambda関数を実行できます。先日イベントソースとしてDocumentDBがサポートされたため、試してみました。
やってみた
作業を進めるにあたって、次の2つの環境は構築済みという前提で進めます。
- VPC
- Cloud9
DocumentDBはユーザーVPCで動作します。また一般的にはプライベートサブネットに配置しますので、それらはあるものとします。一般的なデフォルトVPCで要件としては十分です。
またDocumentDBへのアクセスには、同じVPC内にEC2などを用意する必要があります。SSHトンネリングでローカルからアクセスもできますが、今回はCloud9のターミナルを前提とします。
DocumentDBクラスター作成
まずはDocumentDBクラスターを作成します。いきなりですが、次の制限事項があります。
- エンジンバージョンは 4.0のみ サポート
- 3.6と5.0はサポート外
- Elasticクラスターおよびグローバルクラスターはサポート外
- ペイロードのサイズは6MBまで
つまりエンジンバージョン4.0の、リージョナルクラスターのみが対象ということになります。利用を検討している方は注意してください。
はじめてクラスターを作成する場合は、先にサブネットグループを作成します(defualtが使えるならそれでもOK)。
使用するVPCのプライベートサブネットを指定します。
次にインスタンスベースのクラスターを作成します。
マスターユーザーの設定をします。
残りはデフォルト設定で進め、クラスターを作成します。
ChangeStreams有効化
クラスターが作成できたら、ChangeStremasを有効化しましょう。Cloud9のターミナルからアクセスします。Cloud9へのmongo Shellのインストールなどは、参考URLのGet Started
を参考にしてください。
ChangeStremasの有効化は次のコマンドを実行します。今回は、有効化するデータベースとしてevents
を指定しています。
db.adminCommand({modifyChangeStreams: 1, database: "events", collection: "", enable: true});
Secrets Managerでシークレット作成
クラスター作成時に設定した認証情報をSecrets Managerのシークレットとして登録します。これはLambda関数がDocumentDBへアクセスするために使用されます。
シークレットのタイプは「Amazon DocumentDB データベースの認証情報」です。
データベースとして、先ほど作成したクラスターを選びます。
シークレットの名前として任意の名前を付けます。
残りはデフォルトで問題ありません。
VPCエンドポイント追加
Lambda関数からVPC内のリソースであるDocumentDBにアクセスするため、VPC Lambdaとして作成します。VPC Lambdaは特に設定をしないとVPC外のリソースにアクセスできません。具体的にはVPCエンドポイントかNATゲートウェイを用意する必要があります。
今回はVPCエンドポイントを作成しました。VPCエンドポイントの場合は、次の3つのサービスをサポートする必要があります。
- STS
- Lambda
- Secrets Manager
Lambda関数作成
イベントハンドラとなるLambda関数を作成します。言語はなんでもよいですが、今回はJavaScriptにしました。また処理は単に受け取ったデータをログに出力するだけです。 VPC を有効化 にチェックを入れることを忘れないでください。
export const handler = async(event) => { console.log(event); console.log(event.events[0]); };
IAMロールにポリシー追加
作成したLambda関数に紐付けられているIAMロールにポリシーを追加します。CloudWatch Logsなどの基本的なポリシーはすでにアタッチされているはずですので、差分となる次の権限を追加しましょう。余談ですが、DocumentDBって内部的にはRDSの扱いなんですね。知りませんでした。
ec2:DescribeSecurityGroups ec2:DescribeSubnets ec2:DescribeVpcs kms:Decrypt rds:DescribeDBClusterParameters rds:DescribeDBClusters rds:DescribeDBSubnetGroups secretsmanager:GetSecretValue
Lambda関数のトリガー設定
先ほど作成したLambda関数にトリガーを追加します。ソースとしてDocumentDB
、データベース名にはevents
を指定しています。
認証情報としてBASIC_AUTH
を選択し、Secrets Managers キーに、先ほど追加したシークレットを指定します。
作成したら、有効化されるまで少し待ちましょう。
実行してみる
これで準備が整いました。mongo Shellで次のスニペットを実行します。
use events [...Array(2)].map((_, i) => db.collection.insert({"name":`events_${i}`}))
CloudWatch Logsに次のようなログが出力されました。
{ eventSourceArn: 'arn:aws:rds:ap-northeast-1:123456789012:cluster:docdb-2023-03-29-08-51-34', events: [ { event: [Object] }, { event: [Object] } ], eventSource: 'aws:docdb' } { event: { _id: { _data: '016424dd5c000000060100000006000041f0' }, clusterTime: { '$timestamp': [Object] }, documentKey: { _id: [Object] }, fullDocument: { _id: [Object], name: 'events_0' }, ns: { db: 'events', coll: 'collection' }, operationType: 'insert' } }
まとめ
DocumentDBのChangeStreamsをLambda関数で処理させてみました。DocumentDBのバージョンや、VPC Lambda特有の罠がいくつかあるように感じました。
Lambda関数で処理できるとアーキテクチャ選択にも幅ができますのでとてもいいですね。DocumentDBを利用している方は、ぜひ導入を検討してみてください。